﻿using System;
using System.Linq;
using System.Xml.Linq;

namespace DBAccessTestFramework
{
    public class DatasetElement
    {
        public const string ElementName = "dataset";
        public const string AttributeName = "name";
        public const string AttributeTable = "table";
        public const string AttributeSetIdentityInsert = "setIdentityInsert";
        public const string ElementDataName = "data";

        public string Name { get; set; }

        public string Table { get; set; }

        public bool SetIdentityInsert { get; set; }

        public XElement Data { get; set; }

        public static DatasetElement Load(XElement xml)
        {
            if (xml.Name != ElementName)
            {
                string message = string.Format("Invalid element name: '{0}'. Expected: '{1}'.", xml.Name, ElementName);
                throw new InvalidOperationException(message);
            }

            var result = new DatasetElement();
            result.DecodeAttributes(xml);
            result.DecodeData(xml);
            FileDefinitionHelper.ValidateAttribute(result.Name, ElementName, AttributeName);

            return result;
        }

        private void DecodeData(XElement xml)
        {
            if (xml.Elements().Count() == 0)
            {
                return;
            }

            if (xml.Elements().Count() > 1)
            {
                string message = string.Format("Element '{0}' can have one child only.", DatasetElement.ElementName);
                throw new InvalidOperationException(message);
            }

            var firstNode = xml.Elements().First();
            if (firstNode.Name.LocalName != DatasetElement.ElementDataName)
            {
                string message = string.Format(
                    "Element: '{0}'. Invalid child name '{1}'. Expected: '{2}'.",
                    DatasetElement.ElementName,
                    firstNode.Name.LocalName,
                    DatasetElement.ElementDataName);
                throw new InvalidOperationException(message);
            }

            this.Data = firstNode;
        }

        private void DecodeAttributes(XElement xml)
        {
            string message;
            foreach (var attribute in xml.Attributes())
            {
                switch (attribute.Name.LocalName)
                {
                    case AttributeName:
                        this.Name = attribute.Value;
                        break;
                    case AttributeTable:
                        this.Table = attribute.Value;
                        break;
                    case AttributeSetIdentityInsert:
                        bool result;
                        bool decoded = bool.TryParse(attribute.Value, out result);
                        if (!decoded)
                        {
                            message = string.Format("Element: '{0}'. Invalid attribute '{1}'.", DatasetElement.ElementName, attribute.Name);
                            throw new InvalidOperationException(message);
                        }

                        this.SetIdentityInsert = result;
                        break;
                    default:
                        message = string.Format("Element: '{0}'. Invalid attribute '{1}'.", DatasetElement.ElementName, attribute.Name);
                        throw new InvalidOperationException(message);
                }
            }
        }
    }
}
